package com.mti.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mti.component.snowflake.KeyWorker;
import com.mti.dao.dto.TimeFlow;
import com.mti.dao.kmmodel.GisModel;
import com.mti.dao.kmmodel.KmArmingTaskEntity;
import com.mti.dao.model.LfZdryApproveLogEntity;
import com.mti.dao.model.LfZdryBaseEntity;
import com.mti.dao.model.LfZdryHistoryLogEntity;
import com.mti.dao.model.LfZtryyjEntity;
import com.mti.dao.qo.LfRyyjsjQO;
import com.mti.enums.ApproveStatus;
import com.mti.exception.BusinessException;
import com.mti.jwt.AccountBo;
import com.mti.jwt.RequestUtils;
import com.mti.mapper.KmArmingTaskMapper;
import com.mti.service.IKmArmingTaskService;
import com.mti.service.LfZdryHistoryLogService;
import com.mti.utils.DateUtils;
import com.mti.utils.GetRemoteIpUtil;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.util.Pair;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @author ： caoxx
 * @date ：2020/09/01 16:15
 * @description : 创建布控实现类
 * @path : com.mti.service.impl.KmArmingTaskServiceImpl
 * @modifiedBy ：
 */
@Slf4j
@Service
public class KmArmingTaskServiceImpl extends ServiceImpl<KmArmingTaskMapper, KmArmingTaskEntity> implements IKmArmingTaskService {
	
	@Autowired
	private LfZdryHistoryLogService lfZdryHistoryLogService;
	
	@Autowired
	private GetRemoteIpUtil getRemoteIpUtil;
	
	@Autowired
	private RequestUtils requestUtils;
	
	@Autowired
	private IKmArmingTaskService armingTaskService;
	
	/***
     * @Description: 根据id获取布控任务
     * @Author: caoxx
     * @Date: 2020/9/1 18:06
       @Param: [id]
       @Return: com.mti.dao.kmmodel.KmArmingTaskEntity
     **/
    @Override
    public KmArmingTaskEntity getKmArmingTaskByid(String id) {
        KmArmingTaskEntity taskEntity = this.getOne(new LambdaQueryWrapper<KmArmingTaskEntity>().eq(KmArmingTaskEntity::getId,id));
        if (taskEntity == null){
            throw new BusinessException(500,"未查找到相应数据");
        }else {
            return taskEntity;
        }
    }
    /***
     * @Description: 根据id删除布控任务
     * @Author: caoxx
     * @Date: 2020/9/1 18:06
       @Param: [id]
       @Return: void
     **/
    @Override
    public void deleteKmArmingTaskByid(String id) {
        boolean taskEntity = this.removeById(id);
        if (!taskEntity){
            throw new BusinessException(500,"未查找到先关数据");
        }
    }

    /***
     * @Description: 保存或者修改布控任务内容
     * @Author: caoxx
     * @Date: 2020/9/1 18:06
       @Param: [taskEntity]
       @Return: void
     **/
    @Override
    @Transactional
    public void saveOrUpdateKmArmingTask(KmArmingTaskEntity taskEntity,ServerWebExchange exchange) {
        LocalDateTime now = LocalDateTime.now();
        AccountBo bo = requestUtils.getCurrentUser(exchange);
		if(bo==null) {
			throw new BusinessException(10019,"此账号已在别处登录，请查证");
		}
        if(StringUtils.isEmpty(taskEntity.getId())){
            taskEntity.setId(String.valueOf(KeyWorker.nextId()));
            taskEntity.setCreateDateTime(now);
            this.operatLog("新增",bo, taskEntity, "新增布控任务",exchange);
        }else {
        	// 审批日志表
            this.operatLog("修改",bo, taskEntity, "修改布控任务",exchange);
        }
        taskEntity.setLastUpdateTime(now);
        //如果时间已经比当前时间早则直接启动
        if(taskEntity.getStartDate().isBefore(now) && 0 == taskEntity.getArmingStatus()){
            taskEntity.setArmingStatus(1);
            this.saveRecordData(taskEntity.getId(),taskEntity.getArmingStatus());
        }
        if(null != taskEntity.getArmingStatus() && 3 == taskEntity.getArmingStatus()){
            if(taskEntity.getStartDate().isBefore(now)){
                taskEntity.setArmingStatus(1);
                this.saveRecordData(taskEntity.getId(),taskEntity.getArmingStatus());
            }else{
                taskEntity.setArmingStatus(0);
            }
        }
        if(null!=taskEntity.getArmingStatus() && 1 == taskEntity.getArmingStatus()){
            if(taskEntity.getStartDate().isAfter(now)){
                taskEntity.setArmingStatus(0);
                this.saveRecordData(taskEntity.getId(),taskEntity.getArmingStatus());
            }
        }
        boolean kmArmingTaskEntity = this.saveOrUpdate(taskEntity);
        if (!kmArmingTaskEntity){
            throw new BusinessException(500,"存储或更改相关信息失败");
        }
    }


    @Override
    public void saveRecordData(String taskId, Integer recordStatus) {
        this.baseMapper.saveRecordData(taskId, recordStatus);
    }

    /**
     * @param taskId 布控任务ID
     * @return 时间片段
     */
    private List<TimeFlow> getUsefulTimeRange(String taskId){
        List<Map<String,Object>> list = this.getTimeFlows(taskId);
        boolean checkFlag = true;
        List<TimeFlow> timeFlows = new ArrayList<>();
        TimeFlow pair = null;
        for (int i = 0; i < list.size(); i++) {
            Map<String,Object> item = list.get(i);
            int status = Integer.parseInt(item.get("status").toString());
            boolean startCondition = checkFlag && status == 1;
            if(startCondition){
                pair = new TimeFlow();
                pair.setStartDateTime(item.get("recorddatetime").toString());
                checkFlag = false;
                if(i==list.size()-1){
                    pair.setEndDateTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                    timeFlows.add(pair);
                }
            }
            boolean endCondition = !checkFlag && (status == 2 || status == 3 || status == -1);
            if(endCondition){
                pair.setEndDateTime(item.get("recorddatetime").toString());
                checkFlag = true;
                timeFlows.add(pair);
            }
        }
        return timeFlows;
    }

    @Override
    public boolean setTimeFlows(String taskId,LfRyyjsjQO qo){
        List<TimeFlow> timeFlows = this.getUsefulTimeRange(taskId);
        if(timeFlows!=null && !timeFlows.isEmpty()){
            if(!org.springframework.util.StringUtils.isEmpty(qo.getYjsj_start()) && !org.springframework.util.StringUtils.isEmpty(qo.getYjsj_end())){
                TimeFlow head = timeFlows.get(0);
                TimeFlow tail = timeFlows.get(timeFlows.size()-1);
                LocalDateTime headDateTime = LocalDateTime.parse(head.getStartDateTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                LocalDateTime tailDateTime = LocalDateTime.parse(tail.getEndDateTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                LocalDateTime qoEndDateTime = LocalDateTime.parse(qo.getYjsj_end(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                LocalDateTime qoStartDateTime = LocalDateTime.parse(qo.getYjsj_start(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                if(qoEndDateTime.isBefore(headDateTime) || qoStartDateTime.isAfter(tailDateTime)){
                    return false;
                }
                int startIndex = -1,endIndex = -1;
                for (int i = 0; i < timeFlows.size(); i++) {
                    LocalDateTime start = LocalDateTime.parse(timeFlows.get(i).getStartDateTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                    LocalDateTime end = LocalDateTime.parse(timeFlows.get(i).getEndDateTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                    LocalDateTime preEnd = null;
                    LocalDateTime nextStart = null;
                    if(i>0){
                        preEnd = LocalDateTime.parse(timeFlows.get(i-1).getEndDateTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                    }
                    if(i<timeFlows.size()-1){
                        nextStart = LocalDateTime.parse(timeFlows.get(i+1).getStartDateTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                    }
                    boolean startCondition = (qoStartDateTime.isEqual(start)|| qoStartDateTime.isAfter(start)) && (qoStartDateTime.equals(end)|| qoStartDateTime.isBefore(end));
                    boolean startGapCondition = preEnd != null &&  qoStartDateTime.isBefore(start) && qoStartDateTime.isAfter(preEnd);
                    boolean startPreGapCondition = (i ==0 && qoEndDateTime.isAfter(start) && qoStartDateTime.isBefore(start));
                    if(startCondition || startPreGapCondition || startGapCondition){
                        startIndex = i;
                    }
                    boolean endCondition = (qoEndDateTime.equals(start) || qoEndDateTime.isAfter(start)) && (qoEndDateTime.equals(end)|| qoEndDateTime.isBefore(end));
                    boolean endGapCondition =  nextStart != null && qoEndDateTime.isAfter(end) && qoEndDateTime.isBefore(nextStart);
                    boolean endLastGapCondition = startIndex !=-1 && i==timeFlows.size()-1 && qoEndDateTime.isAfter(end);
                    if(endCondition || endGapCondition || endLastGapCondition){
                        endIndex = i;
                    }
                }
                if(startIndex==-1 && endIndex == -1){
                    qo.setTimeFlows(null);
                    return false;
                }else{
                    if(startIndex!=-1 && endIndex!=-1){
                        timeFlows = timeFlows.subList(startIndex,endIndex+1);
                        LocalDateTime lastHeadStartDateTime = LocalDateTime.parse(timeFlows.get(0).getStartDateTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                        LocalDateTime lastTailEndDateTime = LocalDateTime.parse(timeFlows.get(timeFlows.size()-1).getEndDateTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                        if(qoStartDateTime.isAfter(lastHeadStartDateTime)){
                            timeFlows.get(0).setStartDateTime(qo.getYjsj_start());
                        }
                        if(qoEndDateTime.isBefore(lastTailEndDateTime)){
                            timeFlows.get(timeFlows.size()-1).setEndDateTime(qo.getYjsj_end());
                        }
                    }
                    qo.setTimeFlows(timeFlows);
                }
            }else{
                qo.setTimeFlows(timeFlows);
            }
        }else{
            return false;
        }
        return true;
    }

    @Override
    public List<GisModel> getGisModels(String json){
        if(StringUtils.isEmpty(json))
            return null;
        List<GisModel> gisModels = new ArrayList<>();
        try {
            JSONArray jsonArray = JSONArray.parseArray(json);
            for (int i = 0; i < jsonArray.size(); i++) {
                GisModel gisModel = new GisModel();
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                JSONObject jobj = JSONObject.parseObject(jsonObject.getString("GEOM"));
                JSONArray coordinates = jobj.getJSONArray("coordinates").getJSONArray(0);
                StringBuilder temp = new StringBuilder("POLYGON");
                temp.append("((");
                for (int z = 0; z < coordinates.size(); z++) {
                    JSONArray ja = coordinates.getJSONArray(z);
                    String locateInfoStr = ja.get(0) + " " + ja.get(1);
                    temp.append(locateInfoStr).append(",");
                }
                temp.deleteCharAt(temp.length() - 1);
                temp.append("))");
                String geomText = temp.toString();
                gisModel.setGeom(geomText);
                gisModels.add(gisModel);
            }
        } catch (Exception e) {
            log.error("error==>{}",e.getMessage());
        }
        return gisModels;
    }

    private List<Map<String,Object>> getTimeFlows(String taskId){
        return this.baseMapper.getTimeFlows(taskId);
    }
    /***
     * @Description: 根据布控任务开始时间和布控状态查询任务
     * @Author: caoxx
     * @Date: 2020/9/7 16:06
       @Param: []
       @Return: java.util.List<com.mti.dao.kmmodel.KmArmingTaskEntity>
     **/
    @Override
    public List<String> selectIdByStartDateAndArmingStatus() {
        return baseMapper.selectIdByStartDateAndArmingStatus();
    }
    /***
     * @Description: 根据布控任务结束时间和布控状态查询任务
     * @Author: caoxx
     * @Date: 2020/9/7 16:07
       @Param: []
       @Return: java.util.List<com.mti.dao.kmmodel.KmArmingTaskEntity>
     **/
    @Override
    public List<String> selectIdByEndDateAndArmingStatus() {
        return baseMapper.selectIdByEndDateAndArmingStatus();
    }
    /***
     * @Description: 根据任务id修改布控状态
     * @Author: caoxx
     * @Date: 2020/9/7 16:07
       @Param: [taskId, status]
       @Return: void
     **/
    @Override
    public void updateArmingStatusById(String taskId, Integer status) {
        this.baseMapper.updateArmingStatusById(taskId,status);
    }
    
    /**
	 * 操作日志方法
	 * @param type
	 * @param bo
	 * @param entity
	 * @param logRecord
	 * @return
	 */
	public void operatLog(String type,AccountBo bo,KmArmingTaskEntity taskEntity,String logRecord,ServerWebExchange exchange) {
   		//历史记录
   		LfZdryHistoryLogEntity history = new LfZdryHistoryLogEntity();
        history.setCreator(bo.getPersonBo().getName());
        history.setCreatorCode(bo.getPersonBo().getPoliceCode());
        history.setCreateTime(new Date());
   		history.setSpId(taskEntity.getId());
   		history.setApproveResult(logRecord);
   		history.setOperation(type);
   		history.setOperateDept(bo.getOrganizationBo().getShortName());
   		history.setFunctionModule("布控任务模块");

		ServerHttpRequest request = exchange.getRequest();
		String ip = getRemoteIpUtil.getRemoteIP(request);
		history.setOperateIp(ip);
		//变更
		history.setType(3);
   		lfZdryHistoryLogService.save(history);
	}
	@Override
	public boolean updateStatus(String taskId, Integer status,ServerWebExchange exchange) {
		boolean flag = armingTaskService.update(new LambdaUpdateWrapper<KmArmingTaskEntity>().eq(KmArmingTaskEntity::getId,taskId).set(KmArmingTaskEntity::getArmingStatus,status).set(KmArmingTaskEntity::getLastUpdateTime, LocalDateTime.now()));
        armingTaskService.saveRecordData(taskId, status);
        if(status == -1) {
        	this.operatLog(taskId,exchange);
        }
		return flag;
	}
	
	public void operatLog(String taskId,ServerWebExchange exchange) {
		AccountBo bo = requestUtils.getCurrentUser(exchange);
			if(bo==null) {
				throw new BusinessException(10019,"此账号已在别处登录，请查证");
			}
		//历史记录
   		LfZdryHistoryLogEntity history = new LfZdryHistoryLogEntity();
        history.setCreator(bo.getPersonBo().getName());
        history.setCreatorCode(bo.getPersonBo().getPoliceCode());
        history.setCreateTime(new Date());
   		history.setSpId(taskId);
   		history.setApproveResult("删除布控任务");
   		history.setOperation("删除");
   		history.setOperateDept(bo.getOrganizationBo().getShortName());
   		history.setFunctionModule("布控任务模块");

		ServerHttpRequest request = exchange.getRequest();
		String ip = getRemoteIpUtil.getRemoteIP(request);
		history.setOperateIp(ip);
		//变更
		history.setType(3);
   		lfZdryHistoryLogService.save(history);
	}
	@Override
	public boolean getDefault(String id) {
		this.baseMapper.updateDefault();
		KmArmingTaskEntity entity = new KmArmingTaskEntity();
		entity.setId(id);
		entity.setIsDefault("1");
		boolean flag = armingTaskService.updateById(entity);
		return flag;
	}
	@Override
	public boolean cancelDefault(String id) {
		KmArmingTaskEntity entity = new KmArmingTaskEntity();
		entity.setId(id);
		entity.setIsDefault("0");
		boolean flag = armingTaskService.updateById(entity);
		return flag;
	}

}
